/**
 * \file Файл описания членов класса PlotData2D
 *
 * Файл содержит определение членов класса для отрисовки графика 2D
 */
#include "plotdata2d.h"

PlotData2D::PlotData2D(Gdk::RGBA color,
                       LineStyle line_style,
                       double line_width,
                       ustring name):
       PlotData(color,line_style,line_width),
       m_Y_offset_min(0),   //при первой отрисовки  рисуем без масштабирования на всю высоту холста
       m_Y_offset_max(0)    //при первой отрисовки  рисуем без масштабирования на всю высоту холста
        {
            SetName(name);
        }

 void PlotData2D::AddDataToX(unsigned long long x) {
     this->m_x.push_back(x);
}

 void PlotData2D::AddDataToY(double y) {
     this->m_y.push_back(y);
}

double PlotData2D::GetMinOffsetY() {

    return this->m_Y_offset_min;
}

double PlotData2D::GetMaxOffsetY() {

    return this->m_Y_offset_max;
}


void PlotData2D::CalculateMaxMin(uint32_t x_interval_begin,
                                 uint32_t x_interval_end) {

        std::pair<circular_buffer<unsigned long long>::iterator,circular_buffer<unsigned long long>::iterator> iterMinMaxX;
        std::pair<circular_buffer<double>::iterator, circular_buffer<double>::iterator> iterMinMaxY;

        auto i = m_x.begin();
        advance(i, x_interval_begin);
        auto j = m_y.begin();
        advance(j, x_interval_begin);
        auto i1 = m_x.end();
        auto j1 = m_y.end();

            if (x_interval_end != 0) {
                    i1 = m_x.begin();
                    advance(i1, x_interval_end);
                    j1 = m_y.begin();
                    advance(j1, x_interval_end);
                }
        iterMinMaxX = boost::minmax_element(i, i1);
        iterMinMaxY = boost::minmax_element(j, j1);

        m_x_min = *iterMinMaxX.first;
        m_x_max = *iterMinMaxX.second;
        m_y_min = *iterMinMaxY.first;
        m_y_max = *iterMinMaxY.second;
}

void PlotData2D::DataDraw(const Cairo::RefPtr<Cairo::Context> &cr,
                          uint16_t width,
                          uint16_t height,
                          uint32_t x_interval_begin,
                          uint32_t x_interval_end,
                          double y_offset_min,
                          double y_offset_max) {

        unsigned long long  x;//значения из массива X
        double  y;//значения из массива Y
        double  x_cor;//координаты для cairo
        double  y_cor;//координаты для cairo

        circular_buffer<unsigned long long>::iterator   iterX;
        circular_buffer<double>::iterator               iterY;

        if (y_offset_min !=0 ) m_Y_offset_min = y_offset_min;
        if (y_offset_max != 0) m_Y_offset_max = y_offset_max;
        if (y_offset_min == 999) m_Y_offset_min = 0;
        if (y_offset_max == 999) m_Y_offset_max = 0;

        CalculateMaxMin(x_interval_begin, x_interval_end);

        cr->save();
        auto j = m_x.begin();
            advance(j, x_interval_begin);
                iterX = j;
                    auto g = m_y.begin();
                        advance(g, x_interval_begin);
                            iterY = g;
                            auto j1 = m_x.end();
                                if (x_interval_end != 0) {
                                        j1 = m_x.begin();
                                        advance(j1, x_interval_end);
                                    }
                    for (auto i = j;i != j1;i++)
                    {
                        x = *iterX;
                        y = *iterY;
                        x_cor = width * X_OFFSET_LEFT + (x - m_x_min) * ((width - width * X_OFFSET_RIGHT) / (m_x_max - m_x_min));
                        y_cor = height * Y_OFFSET_UP + (height - height * Y_OFFSET_DOWN) - (y - m_y_min * (1 +  2 * m_Y_offset_min )) *
                        ((height-height * Y_OFFSET_DOWN) /(m_y_max * (1 + m_Y_offset_max + m_Y_offset_min) - m_y_min * (1 + m_Y_offset_max + m_Y_offset_min)));
                        cr -> line_to(x_cor, y_cor);
                        iterX++;
                        iterY++;
                    }
        cr->set_line_width(m_line_width);
        cr->set_source_rgba( m_color.get_red(),m_color.get_green(),m_color.get_blue(),m_color.get_alpha());
        cr ->move_to(0,0);
        cr->stroke();
        cr->restore();
}

uint32_t PlotData2D::GetSize()
{
    return m_x.size();
}

unsigned long long PlotData2D::GetMinX()
{
    return m_x_min;
}

unsigned long long PlotData2D::GetMaxX()
{
    return m_x_max;
}

double PlotData2D::GetMinY()
{
    return m_y_min-(m_y_max - m_y_min) * m_Y_offset_min;
}

double PlotData2D::GetMaxY()
{
    return m_y_max+(m_y_max - m_y_min) * m_Y_offset_max;
}
